using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Configuration;
using System.Windows.Forms;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace Rapier.Kodachi.Shared
{
    public abstract class Plugin
    {
        #region Properties
        private string _Name;
        public string Name
        {
            get { return _Name; }
            protected set { _Name = value; }
        }

        public Guid _Guid;
        public Guid Guid
        {
            get { return _Guid; }
            protected set { _Guid = value; }
        }

        private string _Version;
        public string Version
        {
            get { return _Version; }
            protected set { _Version = value; }
        }

        protected string _Copyright;
        public string Copyright
        {
            get { return _Copyright; }
            protected set { _Copyright = value; }
        }

        private string _Description;
        public string Description
        {
            get { return _Description; }
            protected set { _Description = value; }
        }

        private bool _Enabled = true;
        public bool Enabled
        {
            get { return _Enabled; }
            set { _Enabled = value; }
        }

        public abstract string Author
        {
            get;
        }

        public abstract string Url
        {
            get;
        }

        private Dictionary<string, string> _Messages = new Dictionary<string,string>();
        public Dictionary<string, string> Messages
        {
            get { return _Messages; }
            protected set { _Messages = value; }
        }

        public abstract bool HasSettings
        {
            get;
        }

        private Dictionary<System.Windows.Forms.Keys, Item> _HoldKeys = new Dictionary<System.Windows.Forms.Keys, Item>();
        public Dictionary<System.Windows.Forms.Keys, Item> HoldKeys
        {
            get { return _HoldKeys; }
            set { _HoldKeys = value; }
        }

        private Host _Host;
        public Host Host
        {
            get { return _Host; }
            set { _Host = value; }
        }
        #endregion

        #region Constructor
        public Plugin(Host host)
        {
            Host = host;

            Assembly assembly = Assembly.GetAssembly(this.GetType());
            Name = GetName(assembly);
            Guid = GetGuid(assembly);
            Version = GetVersion(assembly);
            Copyright = GetCopyright(assembly);
            Description = GetDescription(assembly);
        }

        #endregion

        #region Event Declarations
        public event CancelEventHandler EditSettings;
        #endregion

        #region Methods
        public abstract void UpdateDatabase();

        public virtual void ExtendItem(Item item) { }

        /// <summary>
        /// Show settings plugin's settings dialog here.
        /// </summary>
        /// <returns>true if restart needed upon return.</returns>
        public virtual bool ShowSettings()
        {
            return false;
        }

        public virtual void SaveSettings()
        {
        }
        #endregion

        #region Event Callers
        protected virtual void OnEditSettings(CancelEventArgs e)
        {
            foreach (CancelEventHandler handler in EditSettings.GetInvocationList())
            {
                handler.Invoke(this, e);
                if (e.Cancel)
                    break;
            }
        }
        #endregion

        #region Overrides
        public override string ToString()
        {
            return _Name;
        }
        #endregion

        #region Private Methods
        private string GetName(Assembly assembly)
        {
            object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);

            if (attributes.Length == 0)
                return this.GetType().ToString();

            return ((AssemblyTitleAttribute)attributes[0]).Title;
        }

        private Guid GetGuid(Assembly assembly)
        {
            object[] attributes = assembly.GetCustomAttributes(typeof(GuidAttribute), false);

            if (attributes.Length == 0)
                throw new ApplicationException("Plugin '" + this.Name + "' does not have a Guid defined.");

            return new Guid(((GuidAttribute)attributes[0]).Value);
        }

        private string GetVersion(Assembly assembly)
        {
            return assembly.GetName().Version.ToString();
        }

        private string GetCopyright(Assembly assembly)
        {
            object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);

            if (attributes.Length == 0)
                return "Unknown";

            return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
        }

        private string GetDescription(Assembly assembly)
        {
            object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);

            if (attributes.Length == 0)
                return String.Empty;

            return ((AssemblyDescriptionAttribute)attributes[0]).Description;
        }
        #endregion

    }
}
